---@class Formulas
Formulas = ClientFight.CreateClass("Formulas")
local this = Formulas
---@param fighter Fighter
---@param target Fighter
function this.calculateNormalAttackHitrate( fighter, target)
    local fight = fighter.fight
    if (FighterStateEnum.is(target, FighterStateEnum.MUST_BE_HIT)) then
        --必定被命中
        return true;
    end
    local hitrate = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.HITRATE);
    local dodge = FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.DODGE);
    hitrate = hitrate - dodge + Global.FIGHT_HITRATE_BASE;
    hitrate = hitrate + calcRatio(math.min(2000, math.max(-2000, (fighter.level - target.level) * 100)), fight.hitrate_suppress);
    hitrate = math.min(10000, math.max(0, hitrate));
    local random = fight:random(ClientFight.Global.TEN_THOUSANDTH);
    return random <= hitrate;
end
---计算atk属性
---@param fighter Fighter
---@param target Fighter
function this.calculateAtkAttr( fighter,  target,  calculateAttrType, heal)
    if (calculateAttrType == SkillHurtTypeEnum.ATT) then
        local atk = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.ATK);
        if (heal) then
            return atk;
        end
        local ignoreAtkRatio = FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.IGNORE_ATK);
        return atk - calcRatio(atk, ignoreAtkRatio);
    elseif (calculateAttrType == SkillHurtTypeEnum.DEF) then
        local def = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.DEF);
        if (heal) then
            return def;
        end
    local ignoreDefRatio = FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.IGNORE_DEF);
        return def - calcRatio(def, ignoreDefRatio);
    elseif (calculateAttrType == SkillHurtTypeEnum.HP) then
        return FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.HP);
    elseif (calculateAttrType == SkillHurtTypeEnum.LOSE_HP) then
        return FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.HP) - fighter.hp
    end
    return 0
end
---计算减伤率
---@param fighter Fighter
---@param target Fighter
function this.calculateReduceDamageRatio( fighter, target, damageType)
    local reduce = 0;
    local strike = 0;
    if (damageType == SkillDamageTypeEnum.PHYSICS) then
        reduce = FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.PHYSICAL_DAMAGE); -- 物理减伤
        strike = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.PHYSICAL_STRIKE);-- 物理穿透
    elseif (damageType == SkillDamageTypeEnum.MAGIC) then
        reduce = FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.MAGIC_DAMAGE); -- 魔法减伤
        strike = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.MAGIC_STRIKE);-- 魔法穿透
    end
    return math.floor(math.min(math.max(reduce - strike, 0), 10000))
end
---计算暴击伤害率
---@param fighter Fighter
---@param target Fighter
function this.calculateCritDamageRatio(fighter, target, damageType)
    local crit = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.CRITRATE);
    local critRes = FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.CRIT_RES); -- 暴击韧性
    if (damageType == SkillDamageTypeEnum.HOLY) then
        critRes = critRes + FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.CRIT_RES_41); -- 特定条件下的暴击韧性
    end
    local critRatio = crit - critRes;
    local random = fighter.fight:random(ClientFight.Global.TEN_THOUSANDTH);
    if (random <= critRatio or FighterStateEnum.is(fighter, FighterStateEnum.MUST_CRITICAL)) then
        return ClientFight.Global.CRIT_BASE_DAMAGE + FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.CRITDAMAGE);
    end
    return 0;
end
---计算等级压制率
---@param fighter Fighter
---@param target Fighter
function this.calculateLevelSuppressRatio(fighter, target)
    local fight = fighter.fight
    if (fight.fightType == FightTypeConst.DUNGEON) then
        if (fighter.teamIndex == 0) then
            if (fighter.level >= target.level) then
                return 0;
            end
        elseif (fighter.teamIndex == 1) then
            if (fighter.level <= target.level) then
                return 0;
            end
        end
    end
    if (fight.damage_suppress > 0) then
        local level = fighter.level - target.level;
        --if (fighter.level > 30 and target.level > 30) then
            return math.max(0.2, 1 + math.round(fight.damage_suppress / 100.0 * level * math.abs(level)) / 100.0);
        --end
    end
    return 0;
end